//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#ifndef _M_BUF_H___
#define _M_BUF_H___

#include <eladef.h>
#include "netqueue.h"

struct mbuf;
#define MSIZE 256
#define MLEN        (MSIZE - sizeof(struct m_hdr))  /* normal data len */
#define MHLEN       (MLEN - sizeof(struct pkthdr))  /* data len w/pkthdr */

struct m_hdr {
    struct  mbuf *mh_next;      /* next buffer in chain */
    struct  mbuf *mh_nextpkt;   /* next chain in queue/record */
    byte*   mh_data;        /* location of data */
    int mh_len;         /* amount of data in this mbuf */
    int mh_flags;       /* flags; see below */
    short   mh_type;        /* type of data in this mbuf */
};



struct m_tag {
    SLIST_ENTRY(m_tag)  m_tag_link; /* List of packet tags */
    uint16_t       m_tag_id;   /* Tag ID */
    uint16_t       m_tag_len;  /* Length of data */
    uint32_t       m_tag_cookie;   /* ABI/Module ID */
};


struct pkthdr {
    struct  ifnet *rcvif;       /* rcv interface */
    int len;            /* total packet length */
    /* variables for ip and tcp reassembly */
    void    *header;        /* pointer to packet header */
    /* variables for hardware checksum */
    int csum_flags;     /* flags regarding checksum */
    int csum_data;      /* data field used by csum routines */
    SLIST_HEAD(packet_tags, m_tag) tags; /* list of packet tags */
};

struct m_ext {
    caddr_t ext_buf;        /* start of buffer */
    void    (*ext_free)     /* free routine if not the usual */
            (void *, void *);
    void    *ext_args;      /* optional argument pointer */
    uint32_t   ext_size;       /* size of buffer, for ext_free */
    uint32_t   *ref_cnt;       /* pointer to ref count info */
    int ext_type;       /* type of external storage */
};

struct mbuf {
    struct  m_hdr m_hdr;
    union {
        struct {
            struct  pkthdr MH_pkthdr;   /* M_PKTHDR set */
            union {
                struct  m_ext MH_ext;   /* M_EXT set */
                char    MH_databuf[MHLEN];
            } MH_dat;
        } MH;
        char    M_databuf[MLEN];        /* !M_PKTHDR, !M_EXT */
    } M_dat;
};

#define m_next      m_hdr.mh_next
#define m_len       m_hdr.mh_len
#define m_data      m_hdr.mh_data
#define m_type      m_hdr.mh_type
#define m_flags     m_hdr.mh_flags
#define m_nextpkt   m_hdr.mh_nextpkt
#define m_act       m_nextpkt
#define m_pkthdr    M_dat.MH.MH_pkthdr
#define m_ext       M_dat.MH.MH_dat.MH_ext
#define m_pktdat    M_dat.MH.MH_dat.MH_databuf
#define m_dat       M_dat.M_databuf


#define M_DONTWAIT  0x4     /* don't conflict with M_NOWAIT */
#define M_TRYWAIT   0x8     /* or M_WAITOK */
#define M_WAIT      M_TRYWAIT   /* XXX: Deprecated. */
#define MT_NOTMBUF  0   /* USED INTERNALLY ONLY! Object is not mbuf */
#define MT_DATA     1   /* dynamic (data) allocation */
#define MT_HEADER   2   /* packet header */

#define M_EXT       0x0001  /* has associated external storage */
#define M_PKTHDR    0x0002  /* start of record */
#define M_EOR       0x0004  /* end of record */
#define M_RDONLY    0x0008  /* associated data is marked read-only */
#define M_PROTO1    0x0010  /* protocol-specific */
#define M_PROTO2    0x0020  /* protocol-specific */
#define M_PROTO3    0x0040  /* protocol-specific */
#define M_PROTO4    0x0080  /* protocol-specific */
#define M_PROTO5    0x0100  /* protocol-specific */
#define M_FREELIST  0x8000  /* mbuf is on the free list */

#define mtod(m, t)  ((t)((m)->m_data))
#define dtom(x)     ((struct mbuf *)((intptr_t)(x) & ~(MSIZE-1)))

#define SW_INT(n)               ASM("int %0;": :"i"(n))
#define KASSERT(exp,msg)    do { if (!(exp)) SW_INT(3); } while (0)





EXTERN_C void     m_freem(struct mbuf *);
EXTERN_C struct mbuf *m_gethdr(int how, short type);
EXTERN_C void    m_clget(struct mbuf *, int);
EXTERN_C void  m_copydata(const struct mbuf *, int, int, caddr_t);








#endif//_M_BUF_H___
